/// Copyright (c) Microsoft Corporation.  All rights reserved.
/// 
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using Microsoft.VSPowerToys.Common.TaskManager;
using Microsoft.VSPowerToys.PackInstallerDataModel;


namespace Microsoft.VSPowerToys.PackInstaller
{
    public partial class LicenseAgreementDownloadForm : Form
    {
        private PackLibrary packData = null;

        private int totalLicensesToDownload;
        private int actualLicensesDownloaded;

        /// <summary>
        /// Constructor, takes in the list of packs and tools and uses it to figure out how many licenses will be downloaded.
        /// </summary>
        /// <param name="newPackData"></param>
        public LicenseAgreementDownloadForm(PackLibrary newPackData)
        {
            InitializeComponent();
            this.packData = newPackData;
            foreach (ToolItem tool in newPackData.Tools)
            {
                if (tool.InstallTool)
                {
                    totalLicensesToDownload++;
                }
            }

            totalProgressBar.Value = 0;
            this.totalProgressBar.Maximum = totalLicensesToDownload;

            percentCompleteLabel.Text = string.Empty;
            fileSizeLabel.Text = string.Empty;
        }

        /// <summary>
        /// This method creates the tasks necessary for downloading each of the licenses needed.
        /// </summary>
        public void DownloadLicenses()
        {
            TaskScheduler mgr = new TaskScheduler();
            mgr.TaskCompleted += new EventHandler<TaskCompletedEventArgs>(mgr_TaskCompleted);
            mgr.QueueCompleted += new EventHandler(mgr_QueueCompleted);
            mgr.TaskStarting += new EventHandler<TaskEventArgs>(mgr_TaskStarting);
            foreach (ToolItem tool in packData.Tools)
            {
                if (tool.InstallTool)
                {
                    string fileName = Path.Combine(Application.CommonAppDataPath, tool.LicenseAgreementFileName);
                    DownloadTask task = new DownloadTask(tool.LicenseAgreementUrl, fileName);
                    task.ProgressAvailable += new EventHandler<TaskProgressEventArgs>(DownloadTaskProgressAvailable);
                    task.Tag = tool;
                    mgr.EnqueueTask(task);
                }
            }
            mgr.Start();
        }

        /// <summary>
        /// This event gets raised when a task is starting.
        /// We want to set the name of the tool whose license is being downloaded.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void mgr_TaskStarting(object sender, TaskEventArgs e)
        {
            if (!this.InvokeRequired)
            {
                ToolItem currentTool = e.Task.Tag as ToolItem;
                if (currentTool != null)
                {
                    this.currentToolNameLabel.Text = currentTool.ToolName;
                }
            }
            else
            {
                if (!this.IsDisposed)
                    this.Invoke(new EventHandler<TaskEventArgs>(mgr_TaskStarting), sender, new TaskEventArgs(e.Task));
            }
        }

        /// <summary>
        /// This event gets raised when the queue of tasks to be completed is empty.
        /// When all the tasks are done we need to figure out if we got all the licenses.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void mgr_QueueCompleted(object sender, EventArgs e)
        {
            if (!this.InvokeRequired)
            {
                ((TaskScheduler)sender).Stop(false);
                if (this.actualLicensesDownloaded == this.totalLicensesToDownload)
                {
                    this.DialogResult = DialogResult.OK;
                    this.Close();
                }
                else
                {
                    this.errorLabel.Visible = true;
                    this.closeButton.Enabled = true;
                    this.currentDownloadProgressBar.Visible = false;
                    this.pleaseWaitLabel.Visible = false;
                }
            }
            else
            {
                this.Invoke(new EventHandler(mgr_QueueCompleted), sender, e);
            }
        }

        /// <summary>
        /// This event gets raised when a task is completed.  If the task was successful then we increment
        /// the number of downloaded licenses.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void mgr_TaskCompleted(object sender, TaskCompletedEventArgs e)
        {
            TaskScheduler sendingTaskManager = sender as TaskScheduler;
            if (sendingTaskManager != null)
            {
                if (!this.InvokeRequired)
                {
                    if (e.IsSuccess)
                    {
                        this.actualLicensesDownloaded++;
                    }
                    UpdatePercentComplete();
                }
                else
                {
                    this.Invoke(new EventHandler<TaskCompletedEventArgs>(this.mgr_TaskCompleted), sender, e);
                }
            }
            else
            {
                throw new ArgumentException(PackInstaller.Strings.TaskManagerArgumentExceptionErrorMessage, "sender");
            }
        }

        /// <summary>
        /// This event updates the status bar as the download tasks fire off.
        /// </summary>
        /// <param name="sender" />
        /// <param name="e" />
        void DownloadTaskProgressAvailable(object sender, TaskProgressEventArgs e)
        {
            if (!this.InvokeRequired)
            {
                this.currentDownloadProgressBar.Maximum = e.MaximumProgressValue;
                this.currentDownloadProgressBar.Minimum = 0;
                this.currentDownloadProgressBar.Value = e.CurrentProgress;
                this.fileSizeLabel.Text = (e.CurrentProgress / 1024).ToString("N0", Application.CurrentCulture.NumberFormat) +
                    PackInstaller.Strings.DownloadProgressKBLabelText + "/" + (e.MaximumProgressValue / 1024).ToString("N0", Application.CurrentCulture.NumberFormat) +
                    PackInstaller.Strings.DownloadProgressKBLabelText;
            }
            else
            {
                this.Invoke(new EventHandler<TaskProgressEventArgs>(this.DownloadTaskProgressAvailable), sender, new TaskProgressEventArgs(e.CurrentTask, e.CurrentProgress, e.MaximumProgressValue));
            }
        }

        /// <summary>
        /// This event triggers when we show the form, we want to start the downloading when that happens.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void LicenseAgreementDownloadForm_Shown(object sender, EventArgs e)
        {
            DownloadLicenses();
        }

        /// <summary>
        /// This method updates the % complete indicator.
        /// </summary>
        private void UpdatePercentComplete()
        {
            totalProgressBar.Increment(1);
            totalProgressBar.Refresh();
            percentCompleteLabel.Text = ((int)(((double)totalProgressBar.Value / (double)totalProgressBar.Maximum) * 100.0)).ToString(Application.CurrentCulture.NumberFormat) + '%';
            percentCompleteLabel.Refresh();
            this.Refresh();
        }
    }
}